package solutions.ferpa.ztest.intf;

import br.com.telescope.adsrt.dom.DomId;
import br.com.telescope.adsrt.dom.DomOpcao;
import br.com.telescope.adsrt.dom.DomSelectionCheck;
import br.com.telescope.adsrt.dom.DomText;
import br.com.telescope.adsrt.dom.DomTextLong;
import br.com.telescope.adsrt.dom.DomUpper;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.adsrt.lib.AdsException;
import br.com.telescope.adsrt.lib.Field;
import br.com.telescope.t2.ServiceModel;
import br.com.telescope.t2.exception.ApplicationRuntimeException;
import br.com.telescope.t2.exception.UnexpectedException;
import br.com.telescope.t2.feature.DeleteFeature;
import br.com.telescope.t2.feature.InsertFeature;
import br.com.telescope.t2.feature.ListFeature;
import br.com.telescope.t2.feature.QueryFeature;
import br.com.telescope.t2.feature.UpdateFeature;
import br.com.telescope.util.JdbcUtil;
import br.com.telescope.util.TextBuilder;
import java.util.ArrayList;
import java.util.List;
import solutions.ferpa.ztest.ent.*;

/**
 * Funções que acessam a interface.
 * <p>
 * Interface que permite administrar quais as funções que acessam uma 
 * determinada interface.
 * <P>
 * Telescope origin: RTSYSINF.CAD_INTERFACE_FUNCAO
 * <P>
 * Base entity: RTSYSINF.INTERFACES_FUNCOES
 * <P>
 * @author TELESCOPE - Build task T2 Web Interface Generator
 * <P>
 * @version 0.1
 */
public class CadInterfaceFuncao extends ServiceModel {
    
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    public static final String GLOBAL_NAME = "RTSYSINF.CAD_INTERFACE_FUNCAO";
    
    @Override
    public String globalName() {
        return GLOBAL_NAME;
    }
    
    {
        setTitle("Funções que acessam a interface");
    }
    
    protected EntInterfacesFuncoes base;
    protected EntFuncoesSistemas func;
    protected EntInterfacesFuncoes rec; // NEED_TJW1_COMPATIBILITY
    
    // Service parameters
    private DomId pInterfaceId;
    
    // Record items
    private DomId aId;
    private DomId aInterfaceId;
    private DomOpcao aFuncaoId;
    private DomUpper aFuncaoSistema;
    private DomText aTitulo;
    private DomText aOperacoesList;
    private DomTextLong aUsuarios;
    private DomSelectionCheck aOperacoes;
    
    // Query items
    private DomText qTitulo;
    private DomUpper qFuncaoSistema;
    
    @Override
    public String getBaseSql() {
        return "select BASE.*"
                + " , FUNC.FUNCAO_SISTEMA as FUNCAO_SISTEMA"
                + " , FUNC.TITULO as TITULO"
                + " , FUNC.ID as Z_FUNC_ID"
                + " from INTERFACES_FUNCOES BASE"
                + " join FUNCOES_SISTEMAS FUNC on FUNC.ID = BASE.FUNCAO_ID";
    }
    
    @Override
    public void initAttributes() {
        
        aId = new DomId();
        aId.context(ctx).name("ID").label("Id");
        
        aInterfaceId = new DomId();
        aInterfaceId.context(ctx).name("INTERFACE_ID").label("Interface");
        
        aFuncaoId = new DomOpcao();
        aFuncaoId.context(ctx).name("FUNCAO_ID").label("Função").group(true);
        
        aFuncaoSistema = new DomUpper();
        aFuncaoSistema.context(ctx).name("FUNCAO_SISTEMA").label("Função");
        aFuncaoSistema.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT FUNCAO_SISTEMA as valor"
                + " , FUNCAO_SISTEMA as pesquisar"
                + " , FUNCAO_SISTEMA as descricao"
                + " from FUNCOES_SISTEMAS FUNC)", "q"));
        aFuncaoSistema.setAutocompleteLength(1);
        
        aTitulo = new DomText();
        aTitulo.context(ctx).name("TITULO").label("Título");
        aTitulo.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT TITULO as valor"
                + " , TITULO as pesquisar"
                + " , TITULO as descricao"
                + " from FUNCOES_SISTEMAS FUNC)", "q"));
        aTitulo.setAutocompleteLength(1);
        
        aOperacoesList = new DomText();
        aOperacoesList.context(ctx).name("OPERACOES_LIST").label("Operações").unbound(true);
        
        aUsuarios = new DomTextLong();
        aUsuarios.context(ctx).name("USUARIOS").label("Usuários").unbound(true);
        
        aOperacoes = new DomSelectionCheck();
        aOperacoes.context(ctx).name("OPERACOES").label("Operações").unbound(true);
        
        
        qTitulo = new DomText();
        qTitulo.context(ctx).name("TITULO").label("Título");
        qTitulo.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT TITULO as valor"
                + " , TITULO as pesquisar"
                + " , TITULO as descricao"
                + " from FUNCOES_SISTEMAS FUNC)", "q"));
        qTitulo.setAutocompleteLength(1);
        
        qFuncaoSistema = new DomUpper();
        qFuncaoSistema.context(ctx).name("FUNCAO_SISTEMA").label("Função");
        qFuncaoSistema.setListOfValuesQuery(createQuery()
                .select("*")
                .from("(SELECT FUNCAO_SISTEMA as valor"
                + " , FUNCAO_SISTEMA as pesquisar"
                + " , FUNCAO_SISTEMA as descricao"
                + " from FUNCOES_SISTEMAS FUNC)", "q"));
        qFuncaoSistema.setAutocompleteLength(1);
    }
    
    @Override
    public void initParameters() {
        pInterfaceId = new DomId(ctx, "INTERFACE_ID", "Interface");
        pInterfaceId.setValue(ctx.getParameter("P_INTERFACE_ID"));
        if (pInterfaceId.isNotNull()) {
            aInterfaceId.setValue(pInterfaceId.getValue());
        }
    }
    
    @Override
    public List<Field> getParameters() {
        if (allParameters == null) {
            allParameters = new ArrayList<Field>();
            allParameters.add(pInterfaceId);
        }
        return allParameters;
    }
    
    @Override
    public void copyBindParameters() {
        EntInterfacesFuncoes record = getRecord();
        if (pInterfaceId.isNotNull()) {
            record.setInterfaceId(pInterfaceId.getValue());
        }
    }
    
    @Override
    public void retrieveBindParameters() {
        pInterfaceId.setValue(getRecord().valueOfInterfaceId());
    }
    
    @Override
    public String getQueryPkColumn() {
        return "BASE.ID";
    }
    
    @Override
    public void setId(String value) {
        this.aId.setValue(value);
    }
    
    @Override
    public EntInterfacesFuncoes getRecord() {
        if (base == null) {
            base = new EntInterfacesFuncoes(ctx);
            rec = base;
        }
        return this.base;
    }
    
    @Override
    public String getContextName() {
        return aFuncaoSistema.toText();
    }
    
    @Override
    public String getDefaultOrderBy() {
        return "FUNCAO_SISTEMA, TITULO";
    }
    
    /**
     * Popula os valores de unbounds
     */
    @Override
    public void calculateUnboundValues() {
        try {
            aOperacoesList.setValue(listaOperacoes());
        } catch (AdsException ex) {
            throw new UnexpectedException("running inference rules", ex);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="QUERY">
    public class FQuery extends QueryFeature {
        
        @Override
        public void initForm() {
            addField(qFuncaoSistema, "opt");
            addField(qTitulo, "opt");
        }
        
        {
            setFeatureName("QUERY");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="LIST">
    public class FList extends ListFeature {
        
        @Override
        public void initForm() {
            addField(aFuncaoSistema, "view");
            addField(aTitulo, "view");
            addField(aOperacoesList, "view");
            addField(aUsuarios, "view");
        }
        
        @Override
        public void preRecord() {
            try {
                apresentarUsuarios();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("LIST");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="INSERT">
    public class FInsert extends InsertFeature {
        
        @Override
        public void initForm() {
            aFuncaoId.setOptional(false);
            addField(aFuncaoId, "rqd");
        }
        
        @Override
        public void posInsert() {
            try {
                criarAcessosDefault();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void preDisplay() {
            try {
                popularFuncoes();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("INSERT");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="UPDATE">
    public class FUpdate extends UpdateFeature {
        
        @Override
        public void initForm() {
            aFuncaoSistema.setEditable(false);
            addField(aFuncaoSistema, "view");
            aTitulo.setEditable(false);
            addField(aTitulo, "view");
            aOperacoes.setOptional(false);
            addField(aOperacoes, "rqd");
        }
        
        @Override
        public void preDisplay() {
            try {
                popularOperacoesUpdate();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void posUpdate() {
            try {
                salvarOperacoes();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("UPDATE");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="DELETE">
    public class FDelete extends DeleteFeature {
        
        @Override
        public void initForm() {
            addField(aFuncaoSistema, "view");
        }
        
        {
            setFeatureName("DELETE");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="initFeatures">
    
    @Override
    protected void initFeatures() {
        addFeature(new FQuery());
        addFeature(new FList());
        addFeature(new FInsert());
        addFeature(new FUpdate());
        addFeature(new FDelete());
        super.initFeatures();
    }
    
    @Override
    public String getDefaultFeature() {
        return "QUERY";
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Getters and Setters">
    
    @Override
    public Long getId() {
        return aId.getValue();
    }
    
    public void setId(Long value) {
        this.aId.setValue(value);
    }
    
    public Long getInterfaceId() {
        return aInterfaceId.getValue();
    }
    
    public void setInterfaceId(Long value) {
        this.aInterfaceId.setValue(value);
    }
    
    public String getFuncaoId() {
        return aFuncaoId.getValue();
    }
    
    public void setFuncaoId(String value) {
        this.aFuncaoId.setValue(value);
    }
    
    public String getFuncaoSistema() {
        return aFuncaoSistema.getValue();
    }
    
    public void setFuncaoSistema(String value) {
        this.aFuncaoSistema.setValue(value);
    }
    
    public String getTitulo() {
        return aTitulo.getValue();
    }
    
    public void setTitulo(String value) {
        this.aTitulo.setValue(value);
    }
    
    public String getOperacoesList() {
        return aOperacoesList.getValue();
    }
    
    public void setOperacoesList(String value) {
        this.aOperacoesList.setValue(value);
    }
    
    public String getUsuarios() {
        return aUsuarios.getValue();
    }
    
    public void setUsuarios(String value) {
        this.aUsuarios.setValue(value);
    }
    
    public String getOperacoes() {
        return aOperacoes.getValue();
    }
    
    public void setOperacoes(String value) {
        this.aOperacoes.setValue(value);
    }
    public String getQueryFuncaoSistema() {
        return qFuncaoSistema.getQueryValue();
    }
    
    public void setQueryFuncaoSistema(String value) {
        this.qFuncaoSistema.setQueryValue(value);
    }
    public String getQueryTitulo() {
        return qTitulo.getQueryValue();
    }
    
    public void setQueryTitulo(String value) {
        this.qTitulo.setQueryValue(value);
    }
    
    public Long getParameterInterfaceId() {
        return pInterfaceId.getValue();
    }
    
    public void setParameterInterfaceId(Long value) {
        pInterfaceId.setValue(value);
        aInterfaceId.setValue(value);
    }
    // </editor-fold>
    
    /**
     * Apresentar usuários.
     * <p>
     * Alimenta um campo com a lista de usuários que tem a função.
     */
    public void apresentarUsuarios() throws AdsException {
        // <user-code id="22327365" parentId="22327348" hashcode="-5a154c08" length="458">
        // import br.com.telescope.util.JdbcUtil;
        // import br.com.telescope.util.TextBuilder;
        TextBuilder texto = new TextBuilder(", ");
        texto.p(JdbcUtil.getList(String.class, "select u.login"
                + " from funcoes_usuarios fuus"
                + " join usuarios u on u.id = fuus.usuario_id"
                + " where fuus.funcao_id = ?"
                + " and u.ativo = 'S'"
                + " order by u.login",
                getRecord().valueOfFuncaoId()));
        aUsuarios.setValue(texto);
        // </user-code>
    }
    
    /**
     * Criar acessos default.
     * <p>
     * Na inclusão de uma interface, todas as operações são incluídas por 
     * default. 
     * <P>
     */
    private void criarAcessosDefault() throws AdsException {
        // <user-code id="806823" parentId="752717" hashcode="-67708bef" length="394">
        EntOperacoesSistemas os = new EntOperacoesSistemas(ads);
        os.find("select id" +
                " from operacoes_sistemas" +
                " where interface_id = ?");
        os.sqlSetLong(1, rec.valueOfInterfaceId());
        while (os.next()) {
            EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
            of.setFuncaoId(rec.valueOfFuncaoId());
            of.setOperacaoId(os.valueOfId());
            of.ins();
        }
        os.close();
        // </user-code>
    }
    
    /**
     * Lista operações.
     * <p>
     * Retorna a lista da operações liberadas.
     */
    private String listaOperacoes() throws AdsException {
        // <user-code id="806827" parentId="752695" hashcode="-14854398" length="562">
        StringBuilder str = new StringBuilder();
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        of.find("select opfu.id" +
                " from operacoes_funcoes opfu" +
                " join operacoes_sistemas os on os.id=opfu.operacao_id" +
                " where opfu.funcao_id = " + rec.valueOfFuncaoId() +
                " and os.interface_id = " + rec.valueOfInterfaceId() +
                " order by os.titulo");
        while (of.next()) {
            if (str.length()>0) str.append(", ");
            str.append(of.findOperacao().valueOfTitulo().toLowerCase());
        }
        of.close();
        return str.toString();
        // </user-code>
    }
    
    /**
     * Popular funções.
     * <p>
     * Popula as opções de funções que podem ser usadas na inclusão (apenas 
     * as funções que ainda não foram inseridas)
     */
    private void popularFuncoes() throws AdsException {
        // <user-code id="806824" parentId="752719" hashcode="-600c2a07" length="389">
        aFuncaoId.addSqlOptions("select distinct f.id, f.funcao_sistema || ' - ' || f.titulo" +
                " from funcoes_sistemas f" +
                " where not exists (" +
                "    select 1" +
                "    from interfaces_funcoes" +
                "    where interface_id=" + pInterfaceId.getValue() + " and funcao_id=f.id" +
                " )" +
                " order by f.funcao_sistema || ' - ' || f.titulo");
        // </user-code>
    }
    
    /**
     * Popular operações para update.
     * <p>
     * Monta as opções de operações existentes para a função informada. 
     * <P>
     * Na implementação Java/j2ee, retorna uma string representante um JSON 
     * com o array de opções e indicando quais são habilitadas.
     */
    private void popularOperacoesUpdate() throws AdsException {
        // <user-code id="806825" parentId="752721" hashcode="55c16a90" length="716">
        aOperacoes.addSqlOptions("select id," +
                " titulo, null" +
                " from operacoes_sistemas" +
                " where interface_id = " + rec.valueOfInterfaceId() +
                " order by titulo");
        StringBuilder str = new StringBuilder();
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        of.find("select opfu.id" +
                " from operacoes_funcoes opfu" +
                " join operacoes_sistemas os on os.id=opfu.operacao_id" +
                " where opfu.funcao_id = " + rec.valueOfFuncaoId() +
                " and os.interface_id = " + rec.valueOfInterfaceId());
        while (of.next()) {
            if (str.length()>0) str.append(",");
            str.append(of.valueOfOperacaoId());
        }
        of.close();
        aOperacoes.setValue(str.toString());
        // </user-code>
    }
    
    /**
     * Salvar operações.
     * <p>
     * Depois de alterar, atualiza os registros das operações que o usuário 
     * selecionou e exclui qualquer uma que não tenha sido selecionada.
     */
    private void salvarOperacoes() throws AdsException {
        // <user-code id="806826" parentId="752723" hashcode="600cc9ec" length="845">
        EntOperacoesFuncoes of = new EntOperacoesFuncoes(ads);
        
        // Excluir os que não existem...
        of.del("select opfu.id" +
                " from operacoes_funcoes opfu" +
                " join operacoes_sistemas os on os.id = opfu.operacao_id" +
                " where opfu.funcao_id = " + rec.valueOfFuncaoId() +
                " and os.interface_id = " + rec.valueOfInterfaceId() +
                " and opfu.operacao_id not in (" + aOperacoes.getValue() + ")");
        
        // Incluir os que faltam ser incluidos
        String[] list = aOperacoes.getValue().split(",");
        for (String sid: list) {
            long operId = Long.parseLong(sid);
            try {
                of.findByOperacaoIdFuncaoId(operId,rec.valueOfFuncaoId());
            } catch (RecordNotFoundException ex) {
                of.nullify();
                of.setFuncaoId(rec.valueOfFuncaoId());
                of.setOperacaoId(operId);
                of.ins();
            }
        }
        // </user-code>
    }
}
